package AES;

import java.util.Arrays;
import java.util.Base64;

/**
 * 手搓AES-128优化版：支持任意文本加密（含填充+Base64编码）
 * 生产环境禁用！仅用于学习原理
 */
public class HandwrittenAES128_Text {
    // ===================== 原有常量（S盒、逆S盒、RCON）不变，已加(byte)强转 =====================
    private static final byte[][] S_BOX = {
            {(byte)0x63, (byte)0x7C, (byte)0x77, (byte)0x7B, (byte)0xF2, (byte)0x6B, (byte)0x6F, (byte)0xC5, (byte)0x30, (byte)0x01, (byte)0x67, (byte)0x2B, (byte)0xFE, (byte)0xD7, (byte)0xAB, (byte)0x76},
            {(byte)0xCA, (byte)0x82, (byte)0xC9, (byte)0x7D, (byte)0xFA, (byte)0x59, (byte)0x47, (byte)0xF0, (byte)0xAD, (byte)0xD4, (byte)0xA2, (byte)0xAF, (byte)0x9C, (byte)0xA4, (byte)0x72, (byte)0xC0},
            {(byte)0xB7, (byte)0xFD, (byte)0x93, (byte)0x26, (byte)0x36, (byte)0x3F, (byte)0xF7, (byte)0xCC, (byte)0x34, (byte)0xA5, (byte)0xE5, (byte)0xF1, (byte)0x71, (byte)0xD8, (byte)0x31, (byte)0x15},
            {(byte)0x04, (byte)0xC7, (byte)0x23, (byte)0xC3, (byte)0x18, (byte)0x96, (byte)0x05, (byte)0x9A, (byte)0x07, (byte)0x12, (byte)0x80, (byte)0xE2, (byte)0xEB, (byte)0x27, (byte)0xB2, (byte)0x75},
            {(byte)0x09, (byte)0x83, (byte)0x2C, (byte)0x1A, (byte)0x1B, (byte)0x6E, (byte)0x5A, (byte)0xA0, (byte)0x52, (byte)0x3B, (byte)0xD6, (byte)0xB3, (byte)0x29, (byte)0xE3, (byte)0x2F, (byte)0x84},
            {(byte)0x53, (byte)0xD1, (byte)0x00, (byte)0xED, (byte)0x20, (byte)0xFC, (byte)0xB1, (byte)0x5B, (byte)0x6A, (byte)0xCB, (byte)0xBE, (byte)0x39, (byte)0x4A, (byte)0x4C, (byte)0x58, (byte)0xCF},
            {(byte)0xD0, (byte)0xEF, (byte)0xAA, (byte)0xFB, (byte)0x43, (byte)0x4D, (byte)0x33, (byte)0x85, (byte)0x45, (byte)0xF9, (byte)0x02, (byte)0x7F, (byte)0x50, (byte)0x3C, (byte)0x9F, (byte)0xA8},
            {(byte)0x51, (byte)0xA3, (byte)0x40, (byte)0x8F, (byte)0x92, (byte)0x9D, (byte)0x38, (byte)0xF5, (byte)0xBC, (byte)0xB6, (byte)0xDA, (byte)0x21, (byte)0x10, (byte)0xFF, (byte)0xF3, (byte)0xD2},
            {(byte)0xCD, (byte)0x0C, (byte)0x13, (byte)0xEC, (byte)0x5F, (byte)0x97, (byte)0x44, (byte)0x17, (byte)0xC4, (byte)0xA7, (byte)0x7E, (byte)0x3D, (byte)0x64, (byte)0x5D, (byte)0x19, (byte)0x73},
            {(byte)0x60, (byte)0x81, (byte)0x4F, (byte)0xDC, (byte)0x22, (byte)0x2A, (byte)0x90, (byte)0x88, (byte)0x46, (byte)0xEE, (byte)0xB8, (byte)0x14, (byte)0xDE, (byte)0x5E, (byte)0x0B, (byte)0xDB},
            {(byte)0xE0, (byte)0x32, (byte)0x3A, (byte)0x0A, (byte)0x49, (byte)0x06, (byte)0x24, (byte)0x5C, (byte)0xC2, (byte)0xD3, (byte)0xAC, (byte)0x62, (byte)0x91, (byte)0x95, (byte)0xE4, (byte)0x79},
            {(byte)0xE7, (byte)0xC8, (byte)0x37, (byte)0x6D, (byte)0x8D, (byte)0xD5, (byte)0x4E, (byte)0xA9, (byte)0x6C, (byte)0x56, (byte)0xF4, (byte)0xEA, (byte)0x65, (byte)0x7A, (byte)0xAE, (byte)0x08},
            {(byte)0xBA, (byte)0x78, (byte)0x25, (byte)0x2E, (byte)0x1C, (byte)0xA6, (byte)0xB4, (byte)0xC6, (byte)0xE8, (byte)0xDD, (byte)0x74, (byte)0x1F, (byte)0x4B, (byte)0xBD, (byte)0x8B, (byte)0x8A},
            {(byte)0x70, (byte)0x3E, (byte)0xB5, (byte)0x66, (byte)0x48, (byte)0x03, (byte)0xF6, (byte)0x0E, (byte)0x61, (byte)0x35, (byte)0x57, (byte)0xB9, (byte)0x86, (byte)0xC1, (byte)0x1D, (byte)0x9E},
            {(byte)0xE1, (byte)0xF8, (byte)0x98, (byte)0x11, (byte)0x69, (byte)0xD9, (byte)0x8E, (byte)0x94, (byte)0x9B, (byte)0x1E, (byte)0x87, (byte)0xE9, (byte)0xCE, (byte)0x55, (byte)0x28, (byte)0xDF},
            {(byte)0x8C, (byte)0xA1, (byte)0x89, (byte)0x0D, (byte)0xBF, (byte)0xE6, (byte)0x42, (byte)0x68, (byte)0x41, (byte)0x99, (byte)0x2D, (byte)0x0F, (byte)0xB0, (byte)0x54, (byte)0xBB, (byte)0x16}
    };

    private static final byte[][] INV_S_BOX = {
            {(byte)0x52, (byte)0x09, (byte)0x6A, (byte)0xD5, (byte)0x30, (byte)0x36, (byte)0xA5, (byte)0x38, (byte)0xBF, (byte)0x40, (byte)0xA3, (byte)0x9E, (byte)0x81, (byte)0xF3, (byte)0xD7, (byte)0xFB},
            {(byte)0x7C, (byte)0xE3, (byte)0x39, (byte)0x82, (byte)0x9B, (byte)0x2F, (byte)0xFF, (byte)0x87, (byte)0x34, (byte)0x8E, (byte)0x43, (byte)0x44, (byte)0xC4, (byte)0xDE, (byte)0xE9, (byte)0xCB},
            {(byte)0x54, (byte)0x7B, (byte)0x94, (byte)0x32, (byte)0xA6, (byte)0xC2, (byte)0x23, (byte)0x3D, (byte)0xEE, (byte)0x4C, (byte)0x95, (byte)0x0B, (byte)0x42, (byte)0xFA, (byte)0xC3, (byte)0x4E},
            {(byte)0x08, (byte)0x2E, (byte)0xA1, (byte)0x66, (byte)0x28, (byte)0xD9, (byte)0x24, (byte)0xB2, (byte)0x76, (byte)0x5B, (byte)0xA2, (byte)0x49, (byte)0x6D, (byte)0x8B, (byte)0xD1, (byte)0x25},
            {(byte)0x72, (byte)0xF8, (byte)0xF6, (byte)0x64, (byte)0x86, (byte)0x68, (byte)0x98, (byte)0x16, (byte)0xD4, (byte)0xA4, (byte)0x5C, (byte)0xCC, (byte)0x5D, (byte)0x65, (byte)0xB6, (byte)0x92},
            {(byte)0x6C, (byte)0x70, (byte)0x48, (byte)0x50, (byte)0xFD, (byte)0xED, (byte)0xB9, (byte)0xDA, (byte)0x5E, (byte)0x15, (byte)0x46, (byte)0x57, (byte)0xA7, (byte)0x8D, (byte)0x9D, (byte)0x84},
            {(byte)0x90, (byte)0xD8, (byte)0xAB, (byte)0x00, (byte)0x8C, (byte)0xBC, (byte)0xD3, (byte)0x0A, (byte)0xF7, (byte)0xE4, (byte)0x58, (byte)0x05, (byte)0xB8, (byte)0xB3, (byte)0x45, (byte)0x06},
            {(byte)0xD0, (byte)0x2C, (byte)0x1E, (byte)0x8F, (byte)0xCA, (byte)0x3F, (byte)0x0F, (byte)0x02, (byte)0xC1, (byte)0xAF, (byte)0xBD, (byte)0x03, (byte)0x01, (byte)0x13, (byte)0x8A, (byte)0x6B},
            {(byte)0x3A, (byte)0x91, (byte)0x11, (byte)0x41, (byte)0x4F, (byte)0x67, (byte)0xDC, (byte)0xEA, (byte)0x97, (byte)0xF2, (byte)0xCF, (byte)0xCE, (byte)0xF0, (byte)0xB4, (byte)0xE6, (byte)0x73},
            {(byte)0x96, (byte)0xAC, (byte)0x74, (byte)0x22, (byte)0xE7, (byte)0xAD, (byte)0x35, (byte)0x85, (byte)0xE2, (byte)0xF9, (byte)0x37, (byte)0xE8, (byte)0x1C, (byte)0x75, (byte)0xDF, (byte)0x6E},
            {(byte)0x47, (byte)0xF1, (byte)0x1A, (byte)0x71, (byte)0x1D, (byte)0x29, (byte)0xC5, (byte)0x89, (byte)0x6F, (byte)0xB7, (byte)0x62, (byte)0x0E, (byte)0xAA, (byte)0x18, (byte)0xBE, (byte)0x1B},
            {(byte)0xFC, (byte)0x56, (byte)0x3E, (byte)0x4B, (byte)0xC6, (byte)0xD2, (byte)0x79, (byte)0x20, (byte)0x9A, (byte)0xDB, (byte)0xC0, (byte)0xFE, (byte)0x78, (byte)0xCD, (byte)0x5A, (byte)0xF4},
            {(byte)0x1F, (byte)0xDD, (byte)0xA8, (byte)0x33, (byte)0x88, (byte)0x07, (byte)0xC7, (byte)0x31, (byte)0xB1, (byte)0x12, (byte)0x10, (byte)0x59, (byte)0x27, (byte)0x80, (byte)0xEC, (byte)0x5F},
            {(byte)0x60, (byte)0x51, (byte)0x7F, (byte)0xA9, (byte)0x19, (byte)0xB5, (byte)0x4A, (byte)0x0D, (byte)0x2D, (byte)0xE5, (byte)0x7A, (byte)0x9F, (byte)0x93, (byte)0xC9, (byte)0x9C, (byte)0xEF},
            {(byte)0xA0, (byte)0xE0, (byte)0x3B, (byte)0x4D, (byte)0xAE, (byte)0x2A, (byte)0xF5, (byte)0xB0, (byte)0xC8, (byte)0xEB, (byte)0xBB, (byte)0x3C, (byte)0x83, (byte)0x53, (byte)0x99, (byte)0x61},
            {(byte)0x17, (byte)0x2B, (byte)0x04, (byte)0x7E, (byte)0xBA, (byte)0x77, (byte)0xD6, (byte)0x26, (byte)0xE1, (byte)0x69, (byte)0x14, (byte)0x63, (byte)0x55, (byte)0x21, (byte)0x0C, (byte)0x7D}
    };

    private static final byte[][] RCON = {
            {(byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00}, // 索引0不用
            {(byte)0x01, (byte)0x00, (byte)0x00, (byte)0x00},
            {(byte)0x02, (byte)0x00, (byte)0x00, (byte)0x00},
            {(byte)0x04, (byte)0x00, (byte)0x00, (byte)0x00},
            {(byte)0x08, (byte)0x00, (byte)0x00, (byte)0x00},
            {(byte)0x10, (byte)0x00, (byte)0x00, (byte)0x00},
            {(byte)0x20, (byte)0x00, (byte)0x00, (byte)0x00},
            {(byte)0x40, (byte)0x00, (byte)0x00, (byte)0x00},
            {(byte)0x80, (byte)0x00, (byte)0x00, (byte)0x00},
            {(byte)0x1B, (byte)0x00, (byte)0x00, (byte)0x00},
            {(byte)0x36, (byte)0x00, (byte)0x00, (byte)0x00}
    };

    private static final int BLOCK_SIZE = 16; // 128位=16字节
    private static final int KEY_SIZE = 16;
    private static final int ROUNDS = 10;
    private static final int WORD_COUNT = 44;

    // ===================== 新增：填充/去填充工具（处理任意长度文本）=====================
    /**
     * PKCS5填充：将字节数组补全到 BLOCK_SIZE（16）的整数倍
     * 填充规则：缺n个字节就补n个0x0n（比如缺3字节补3个0x03）
     */
    private static byte[] pkcs5Pad(byte[] data) {
        int paddingLen = BLOCK_SIZE - (data.length % BLOCK_SIZE);
        byte[] paddedData = new byte[data.length + paddingLen];
        System.arraycopy(data, 0, paddedData, 0, data.length);
        // 填充n个0x0n
        for (int i = data.length; i < paddedData.length; i++) {
            paddedData[i] = (byte) paddingLen;
        }
        return paddedData;
    }

    /**
     * 去除PKCS5填充：从末尾获取填充长度n，截取前data.length - n字节
     */
    private static byte[] pkcs5Unpad(byte[] paddedData) {
        int paddingLen = paddedData[paddedData.length - 1] & 0xFF; // 填充长度（无符号）
        // 验证填充合法性（避免篡改导致异常）
        if (paddingLen < 1 || paddingLen > BLOCK_SIZE) {
            throw new IllegalArgumentException("无效的填充数据");
        }
        // 截取原始数据（去掉填充部分）
        return Arrays.copyOfRange(paddedData, 0, paddedData.length - paddingLen);
    }

    // ===================== 新增：Base64编码工具（密文可读性优化）=====================
    private static String encodeBase64(byte[] data) {
        return Base64.getEncoder().encodeToString(data);
    }

    private static byte[] decodeBase64(String base64Str) {
        return Base64.getDecoder().decode(base64Str);
    }

    // ===================== 原有核心方法（xtime、multiply、轮变换、密钥扩展、加密/解密）不变 =====================
    private static byte xtime(byte a) {
        return (byte) (((a & 0x80) != 0) ? ((a << 1) ^ 0x1B) : (a << 1));
    }
    private static byte multiply(byte a, byte b) {
        byte result = 0x00;
        for (int i = 0; i < 8; i++) {
            if ((b & 0x01) != 0) {
                result ^= a;
            }
            boolean carry = (a & 0x80) != 0;
            a = (byte) (a << 1);
            if (carry) {
                a ^= 0x1B;
            }
            b = (byte) (b >> 1);
        }
        return result;
    }
    private static byte[][] bytesToState(byte[] input) {
        if (input.length != BLOCK_SIZE) {
            throw new IllegalArgumentException("输入必须是16字节（128位）");
        }
        byte[][] state = new byte[4][4];
        for (int col = 0; col < 4; col++) {
            for (int row = 0; row < 4; row++) {
                state[row][col] = input[col * 4 + row];
            }
        }
        return state;
    }

    private static byte[] stateToBytes(byte[][] state) {
        byte[] output = new byte[BLOCK_SIZE];
        for (int col = 0; col < 4; col++) {
            for (int row = 0; row < 4; row++) {
                output[col * 4 + row] = state[row][col];
            }
        }
        return output;
    }
    private static void subBytes(byte[][] state) {
        for (int row = 0; row < 4; row++) {
            for (int col = 0; col < 4; col++) {
                int b = state[row][col] & 0xFF; // 避免负数值（byte范围-128~127，转无符号）
                state[row][col] = S_BOX[b >>> 4][b & 0x0F]; // 高4位行，低4位列
            }
        }
    }

    private static void invSubBytes(byte[][] state) {
        for (int row = 0; row < 4; row++) {
            for (int col = 0; col < 4; col++) {
                int b = state[row][col] & 0xFF;
                state[row][col] = INV_S_BOX[b >>> 4][b & 0x0F];
            }
        }
    }


    private static void shiftRows(byte[][] state) {
        // 第1行左移1
        byte temp = state[1][0];
        state[1][0] = state[1][1];
        state[1][1] = state[1][2];
        state[1][2] = state[1][3];
        state[1][3] = temp;

        // 第2行左移2
        temp = state[2][0];
        state[2][0] = state[2][2];
        state[2][2] = temp;
        temp = state[2][1];
        state[2][1] = state[2][3];
        state[2][3] = temp;

        // 第3行左移3（等价于右移1）
        temp = state[3][3];
        state[3][3] = state[3][2];
        state[3][2] = state[3][1];
        state[3][1] = state[3][0];
        state[3][0] = temp;
    }


    private static void invShiftRows(byte[][] state) {
        // 第1行右移1
        byte temp = state[1][3];
        state[1][3] = state[1][2];
        state[1][2] = state[1][1];
        state[1][1] = state[1][0];
        state[1][0] = temp;

        // 第2行右移2（同左移2）
        temp = state[2][0];
        state[2][0] = state[2][2];
        state[2][2] = temp;
        temp = state[2][1];
        state[2][1] = state[2][3];
        state[2][3] = temp;

        // 第3行右移3（等价于左移1）
        temp = state[3][0];
        state[3][0] = state[3][1];
        state[3][1] = state[3][2];
        state[3][2] = state[3][3];
        state[3][3] = temp;
    }


    private static void mixColumns(byte[][] state) {
        for (int col = 0; col < 4; col++) {
            byte[] colBytes = new byte[4];
            for (int row = 0; row < 4; row++) {
                colBytes[row] = state[row][col];
            }
            // 计算新列值
            state[0][col] = (byte) (xtime(colBytes[0]) ^ multiply((byte) 0x03, colBytes[1]) ^ colBytes[2] ^ colBytes[3]);
            state[1][col] = (byte) (colBytes[0] ^ xtime(colBytes[1]) ^ multiply((byte) 0x03, colBytes[2]) ^ colBytes[3]);
            state[2][col] = (byte) (colBytes[0] ^ colBytes[1] ^ xtime(colBytes[2]) ^ multiply((byte) 0x03, colBytes[3]));
            state[3][col] = (byte) (multiply((byte) 0x03, colBytes[0]) ^ colBytes[1] ^ colBytes[2] ^ xtime(colBytes[3]));
        }
    }


    private static void invMixColumns(byte[][] state) {
        for (int col = 0; col < 4; col++) {
            byte[] colBytes = new byte[4];
            for (int row = 0; row < 4; row++) {
                colBytes[row] = state[row][col];
            }
            // 0xE=14, 0xB=11, 0xD=13, 0x9=9（有限域乘法）
            state[0][col] = (byte) (multiply((byte) 0x0E, colBytes[0]) ^ multiply((byte) 0x0B, colBytes[1]) ^ multiply((byte) 0x0D, colBytes[2]) ^ multiply((byte) 0x09, colBytes[3]));
            state[1][col] = (byte) (multiply((byte) 0x09, colBytes[0]) ^ multiply((byte) 0x0E, colBytes[1]) ^ multiply((byte) 0x0B, colBytes[2]) ^ multiply((byte) 0x0D, colBytes[3]));
            state[2][col] = (byte) (multiply((byte) 0x0D, colBytes[0]) ^ multiply((byte) 0x09, colBytes[1]) ^ multiply((byte) 0x0E, colBytes[2]) ^ multiply((byte) 0x0B, colBytes[3]));
            state[3][col] = (byte) (multiply((byte) 0x0B, colBytes[0]) ^ multiply((byte) 0x0D, colBytes[1]) ^ multiply((byte) 0x09, colBytes[2]) ^ multiply((byte) 0x0E, colBytes[3]));
        }
    }


    private static void addRoundKey(byte[][] state, byte[][] roundKeys, int round) {
        for (int col = 0; col < 4; col++) {
            for (int row = 0; row < 4; row++) {
                // 轮密钥的第round*4 + col个字的第row字节
                state[row][col] ^= roundKeys[round * 4 + col][row];
            }
        }
    }


    private static byte[][] keyExpansion(byte[] key) {
        if (key.length != KEY_SIZE) {
            throw new IllegalArgumentException("AES-128密钥必须是16字节");
        }
        byte[][] roundKeys = new byte[WORD_COUNT][4]; // 44字 × 4字节/字

        // 步骤1：填充前4个字（w0~w3）
        for (int i = 0; i < 4; i++) {
            roundKeys[i][0] = key[i * 4];
            roundKeys[i][1] = key[i * 4 + 1];
            roundKeys[i][2] = key[i * 4 + 2];
            roundKeys[i][3] = key[i * 4 + 3];
        }

        // 步骤2：扩展后续40个字（w4~w43）
        for (int i = 4; i < WORD_COUNT; i++) {
            byte[] temp = Arrays.copyOf(roundKeys[i - 1], 4); // 取前一个字w[i-1]

            if (i % 4 == 0) { // 每4个字一组，组首字需特殊处理
                temp = rotWord(temp); // 循环左移1字节
                temp = subWord(temp); // 每个字节用S盒替换
                temp = xorBytes(temp, RCON[i / 4]); // 异或对应Rcon
            }

            // w[i] = w[i-4] ^ temp
            roundKeys[i] = xorBytes(roundKeys[i - 4], temp);
        }
        return roundKeys;
    }


    private static byte[] rotWord(byte[] word) {
        byte temp = word[0];
        word[0] = word[1];
        word[1] = word[2];
        word[2] = word[3];
        word[3] = temp;
        return word;
    }


    private static byte[] subWord(byte[] word) {
        for (int i = 0; i < 4; i++) {
            int b = word[i] & 0xFF;
            word[i] = S_BOX[b >>> 4][b & 0x0F];
        }
        return word;
    }



    private static byte[] xorBytes(byte[] a, byte[] b) {
        byte[] result = new byte[4];
        for (int i = 0; i < 4; i++) {
            result[i] = (byte) (a[i] ^ b[i]);
        }
        return result;
    }



    // 单分组加密（16字节）- 原有逻辑不变
    public static byte[] encryptBlock(byte[] plaintextBlock, byte[] key) {
        byte[][] state = bytesToState(plaintextBlock);
        byte[][] roundKeys = keyExpansion(key);
        addRoundKey(state, roundKeys, 0);
        for (int round = 1; round <= ROUNDS - 1; round++) {
            subBytes(state);
            shiftRows(state);
            mixColumns(state);
            addRoundKey(state, roundKeys, round);
        }
        subBytes(state);
        shiftRows(state);
        addRoundKey(state, roundKeys, ROUNDS);
        return stateToBytes(state);
    }

    // 单分组解密（16字节）- 原有逻辑不变
    public static byte[] decryptBlock(byte[] ciphertextBlock, byte[] key) {
        byte[][] state = bytesToState(ciphertextBlock);
        byte[][] roundKeys = keyExpansion(key);
        addRoundKey(state, roundKeys, ROUNDS);
        for (int round = ROUNDS - 1; round >= 1; round--) {
            invShiftRows(state);
            invSubBytes(state);
            addRoundKey(state, roundKeys, round);
            invMixColumns(state);
        }
        invShiftRows(state);
        invSubBytes(state);
        addRoundKey(state, roundKeys, 0);
        return stateToBytes(state);
    }

    // ===================== 新增：文本加密/解密主方法（支持任意长度）=====================
    /**
     * 文本加密：字符串 → UTF-8字节 → PKCS5填充 → 分块加密 → Base64密文
     * @param plainText 任意长度文本（支持中文）
     * @param key 16字节AES-128密钥（可通过generateKey生成）
     * @return Base64编码的密文
     */
    public static String encryptText(String plainText, byte[] key) {
        // 1. 文本 → UTF-8字节数组
        byte[] plainBytes = plainText.getBytes(java.nio.charset.StandardCharsets.UTF_8);
        // 2. PKCS5填充（补全到16字节整数倍）
        byte[] paddedBytes = pkcs5Pad(plainBytes);
        // 3. 分块加密（每16字节一个分组）
        byte[] cipherBytes = new byte[paddedBytes.length];
        for (int i = 0; i < paddedBytes.length; i += BLOCK_SIZE) {
            byte[] block = Arrays.copyOfRange(paddedBytes, i, i + BLOCK_SIZE);
            byte[] encryptedBlock = encryptBlock(block, key);
            System.arraycopy(encryptedBlock, 0, cipherBytes, i, BLOCK_SIZE);
        }
        // 4. 密文 → Base64编码（便于存储/传输）
        return encodeBase64(cipherBytes);
    }

    /**
     * 文本解密：Base64密文 → 字节数组 → 分块解密 → PKCS5去填充 → UTF-8文本
     * @param cipherTextBase64 Base64编码的密文
     * @param key 16字节AES-128密钥（与加密密钥一致）
     * @return 原始文本
     */
    public static String decryptText(String cipherTextBase64, byte[] key) {
        // 1. Base64解码 → 密文字节数组
        byte[] cipherBytes = decodeBase64(cipherTextBase64);
        // 2. 验证密文长度是否为16的倍数
        if (cipherBytes.length % BLOCK_SIZE != 0) {
            throw new IllegalArgumentException("密文长度无效（必须是16字节整数倍）");
        }
        // 3. 分块解密
        byte[] paddedBytes = new byte[cipherBytes.length];
        for (int i = 0; i < cipherBytes.length; i += BLOCK_SIZE) {
            byte[] block = Arrays.copyOfRange(cipherBytes, i, i + BLOCK_SIZE);
            byte[] decryptedBlock = decryptBlock(block, key);
            System.arraycopy(decryptedBlock, 0, paddedBytes, i, BLOCK_SIZE);
        }
        // 4. 去除PKCS5填充 → 原始字节 → UTF-8文本
        byte[] plainBytes = pkcs5Unpad(paddedBytes);
        return new String(plainBytes, java.nio.charset.StandardCharsets.UTF_8);
    }

    // ===================== 新增：生成16字节AES-128密钥（方便测试）=====================
    public static byte[] generateAes128Key() {
        byte[] key = new byte[KEY_SIZE];
        // 安全随机生成密钥（实际应用需安全存储，勿打印！）
        new java.security.SecureRandom().nextBytes(key);
        return key;
    }

    // ===================== 优化后的main方法（加密任意文本）=====================
    public static void main(String[] args) {
        try {
            // 1. 生成AES-128密钥（16字节），实际应用需安全存储（如KMS）
            byte[] aesKey = generateAes128Key();
            System.out.println("AES-128密钥（Base64编码，解密需用）：" + encodeBase64(aesKey));
            System.out.println("=====================================");

            // 2. 待加密的任意文本（支持中文、特殊字符、任意长度）
            String plainText = "Hello 手搓AES！这是一段测试文本：123456 + @#$%^&*()几个意思sadasdadaDa";
            System.out.println("原始明文：" + plainText);
            System.out.println("=====================================");

            // 3. 加密文本
            String cipherText = encryptText(plainText, aesKey);
            System.out.println("加密后的密文（Base64）：" + cipherText);
            System.out.println("=====================================");

            // 4. 解密文本
            String decryptedText = decryptText(cipherText, aesKey);
            System.out.println("解密后的明文：" + decryptedText);
            System.out.println("=====================================");

            // 验证加密解密一致性
            if (plainText.equals(decryptedText)) {
                System.out.println("✅ 加密解密成功！明文一致");
            } else {
                System.out.println("❌ 加密解密失败！明文不一致");
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    // 原有bytesToHex方法（保留，用于调试）
    private static String bytesToHex(byte[] bytes) {
        StringBuilder sb = new StringBuilder();
        for (byte b : bytes) {
            sb.append(String.format("%02X", b));
        }
        return sb.toString();
    }
}